﻿// *----------------------------------------------------------------
// Copyright (C) 2017 通通优品
// 版权所有。
// 
// 类名：OAuthAttribute.cs
// 功能描述：TongTongMall.Oauth2.0
// 
// Create User：jym 2017/02/09
// 
// Edit User：UserName,EditTime
// Describe：Describe
// ----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using TongTongMall.Oauth2._0.Models;
using TongTongMall.Oauth2._0.Server;
using TongTongMall.Redis.Cache;
using TongTongMall.Runtime.Caching;
using TongTongMall.Runtime.Session;

namespace TongTongMall.Oauth2._0.Client.Attributes
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class OAuthAttribute : AuthorizeAttribute
    {
        /// <summary>
        /// 自定义验证内容
        /// </summary>
        public Action<HttpActionContext, Dictionary<OAuthClientErrorStatus, string>> OnValidateAuthorzation { get; set; }
        public Action<HttpActionContext, Dictionary<OAuthClientErrorStatus, string>> OnHandleAuthorzation { get; set; }

        public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
        {
            await base.OnAuthorizationAsync(actionContext, cancellationToken);
        }

        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            bool tokenHasExpired = false, tokenHasValid = false;
            var owinContext = OwinHttpRequestMessageExtensions.GetOwinContext(actionContext.Request);

            if (owinContext != null)
            {
                tokenHasExpired = owinContext.Environment.ContainsKey(OAuthStatus.AccessToken_Expire);
                tokenHasValid = owinContext.Environment.ContainsKey(OAuthStatus.Token_Invalid);
            }
            return !tokenHasExpired && !tokenHasValid;
        }

        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            Dictionary<OAuthClientErrorStatus, string> errorStatusDic = new Dictionary<OAuthClientErrorStatus, string>();
            bool tokenHasExpired = false, tokenHasValid = false;
            var owinContext = OwinHttpRequestMessageExtensions.GetOwinContext(actionContext.Request);
            
            if (owinContext != null)
            {
                tokenHasExpired = owinContext.Environment.ContainsKey(OAuthStatus.AccessToken_Expire);
                tokenHasValid = owinContext.Environment.ContainsKey(OAuthStatus.Token_Invalid);
            }
            if (tokenHasValid)
            {
                errorStatusDic.Add(OAuthClientErrorStatus.AccessTokenError, "AccessToken错误。");
            }
            else if (tokenHasExpired)
            {
                errorStatusDic.Add(OAuthClientErrorStatus.AccessTokenExpire, "AccessToken已过期。");
            }
            if (OnHandleAuthorzation != null && errorStatusDic.Count > 0)
            {
                OnHandleAuthorzation.Invoke(actionContext, errorStatusDic);
            }
            else
            {
                actionContext.Response = new AuthenticationFailureMessage(HttpStatusCode.Unauthorized, actionContext.Request,
                    new
                    {
                        error = errorStatusDic.FirstOrDefault().Key,
                        error_message = errorStatusDic.FirstOrDefault().Value
                    });
            }
        }
    }
}

public class AuthenticationFailureMessage : HttpResponseMessage
{
    public AuthenticationFailureMessage(HttpStatusCode reasonPhrase, HttpRequestMessage request, object responseMessage)
        : base(reasonPhrase)
    {
        MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
        Content = new ObjectContent<object>(responseMessage, jsonFormatter);
        RequestMessage = request;
        ReasonPhrase = reasonPhrase.ToString();
    }
}